/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is ART Ontology API.
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2007.
 * All Rights Reserved.
 *
 * ART Ontology API was developed by the Artificial Intelligence Research Group
 * (art.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about the ART Ontology API can be obtained at 
 * http//art.uniroma2.it/owlart
 *
 */

/*
 * Contributor(s): Armando Stellato stellato@info.uniroma2.it
 */
package it.uniroma2.art.owlart.models;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;

import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.model.ARTLiteral;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.navigation.ARTLiteralIterator;
import it.uniroma2.art.owlart.navigation.ARTResourceIterator;
import it.uniroma2.art.owlart.navigation.ARTURIResourceIterator;
import it.uniroma2.art.owlart.navigation.RDFIterator;

/**
 * Interface for OWL (1.0) compliant models
 * 
 * @author Armando Stellato
 * 
 */
public interface OWLModel extends RDFSModel, OWLReasoner {

	/**
	 * adds an annotation property with uri = <code>propertyURI</code>
	 * 
	 * @param propertyURI
	 * @param superProperty
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addAnnotationProperty(String propertyURI, ARTURIResource superProperty,
			ARTResource... graphs) throws ModelUpdateException;

	/**
	 * adds a datatype property with uri = <code>propertyURI</code>
	 * 
	 * @param propertyURI
	 * @param superProperty
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addDatatypeProperty(String propertyURI, ARTURIResource superProperty,
			ARTResource... graphs) throws ModelUpdateException;

	/**
	 * adds an object property with uri = <code>propertyURI</code>
	 * 
	 * @param propertyURI
	 * @param superProperty
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addObjectProperty(String propertyURI, ARTURIResource superProperty,
			ARTResource... graphs) throws ModelUpdateException;

	/**
	 * adds an ontology property with uri = <code>propertyURI</code>
	 * 
	 * @param propertyURI
	 * @param superProperty
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addOntologyProperty(String propertyURI, ARTURIResource superProperty,
			ARTResource... graphs) throws ModelUpdateException;

	/**
	 * adds an import statement to the given ontology graphs. Note that this method should be commonly invoked
	 * on the main graph, since the subject of the import is the uri of the main ontology of this model.
	 * However, the methods allows to state the import also in other graphs
	 * 
	 * @param baseURI
	 *            the baseURI of the ontology being imported
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void addImportStatement(String baseURI, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * creates a triple for the given <code>subject</code>, <code>predicate</code> and <code>value</code><br/>
	 * Arguments are already constrained considering the type of property which is being instantiated
	 * 
	 * @param subject
	 * @param predicate
	 * @param value
	 * @param graphs
	 * @throws ModelUpdateException
	 * 
	 * @deprecated use
	 *             {@link RDFModel#instantiatePropertyWithPlainLiteral(ARTResource, ARTURIResource, String, ARTResource...)}
	 */
	public abstract void instantiateDatatypeProperty(ARTResource subject, ARTURIResource predicate,
			String value, ARTResource... graphs) throws ModelUpdateException;

	/**
	 * creates a triple for the given <code>subject</code>, <code>predicate</code> and <code>object</code><br/>
	 * Arguments are already constrained considering the type of property which is being instantiated
	 * 
	 * @param subject
	 * @param predicate
	 * @param object
	 * @param graphs
	 * @throws ModelUpdateException
	 * 
	 * @deprecated use
	 *             {@link RDFModel#instantiatePropertyWithResource(ARTResource, ARTURIResource, ARTResource, ARTResource...)}
	 */
	public abstract void instantiateObjectProperty(ARTResource subject, ARTURIResource predicate,
			ARTResource object, ARTResource... graphs) throws ModelUpdateException;

	/**
	 * creates a triple for the given <code>subject</code>, <code>predicate</code> and object, which is
	 * described by its label (<code>value</code>) and language (<code>lang</code>)<br/>
	 * Arguments are already constrained considering the type of property which is being instantiated
	 * 
	 * @param subject
	 * @param property
	 * @param value
	 * @param lang
	 * @throws ModelUpdateException
	 * 
	 * @deprecated use
	 *             {@link RDFModel#instantiatePropertyWithPlainLiteral(ARTResource, ARTURIResource, String, String, ARTResource...)}
	 */
	public void instantiateAnnotationProperty(ARTResource subject, ARTURIResource property, String value,
			String lang, ARTResource... graphs) throws ModelUpdateException;

	/**
	 * checks that prop is an Annotation property
	 * 
	 * @param prop
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isAnnotationProperty(ARTURIResource prop, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is an Ontology property
	 * 
	 * @param prop
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isOntologyProperty(ARTURIResource prop, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is an Datatype property
	 * 
	 * @param prop
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isDatatypeProperty(ARTURIResource prop, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is a Functional property
	 * 
	 * @param property
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isFunctionalProperty(ARTURIResource property, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is an InverseFunctional property
	 * 
	 * @param property
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isInverseFunctionalProperty(ARTURIResource property, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is an Object property
	 * 
	 * @param prop
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isObjectProperty(ARTURIResource prop, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is a Symmetric property
	 * 
	 * @param property
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isSymmetricProperty(ARTURIResource property, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * checks that prop is a Transitive property
	 * 
	 * @param property
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isTransitiveProperty(ARTURIResource property, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * 
	 * checks if the resource (which has been probably returned has the range of a datatype property, is a
	 * DataRange)
	 * 
	 * @param range
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isDataRange(ARTResource range, ARTResource... graphs) throws ModelAccessException;

	/**
	 * checks that resource <code>uri</code> is an Ontology
	 * 
	 * @param uri
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean isOntology(ARTURIResource uri, ARTResource... graphs) throws ModelAccessException;

	/**
	 * returns an iterator over datatype properties available from graphs <code>graphs</code>
	 * 
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listDatatypeProperties(boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * returns an iterator over object properties available from graphs <code>graphs</code>
	 * 
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listObjectProperties(boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * returns an iterator over Annotation properties available from graphs <code>graphs</code>
	 * 
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listAnnotationProperties(boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * returns an iterator over Ontology properties available from graphs <code>graphs</code>
	 * 
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listOntologyProperties(boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * returns the inverse property of <code>objectProperty</code>. If more than one inverse is defined, the
	 * first declared one is returned (all other properties are equivalentProperties then). If no declaration
	 * is available, null is returned.
	 * 
	 * @param objectProperty
	 * @param inferred
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResource getInverseProperty(ARTURIResource objectProperty, boolean inferred,
			ARTResource... graphs) throws ModelAccessException;

	/**
	 * list all ontologies imported by ontology <code>ontology</code> (defined in graphs <code>graphs</code>
	 * 
	 * @param ontology
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listOntologyImports(ARTURIResource ontology, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * returns an iterator over the list of values bound to individual <code>individual</code> through
	 * datatype/annotation property <code>property</code> both parameters need to be instantiated
	 * 
	 * @param instance
	 * @param property
	 * @param inferred
	 * @return
	 */
	public abstract ARTLiteralIterator listValuesOfSubjDTypePropertyPair(ARTResource instance,
			ARTURIResource property, boolean inferred, ARTResource... graphs) throws ModelAccessException;

	/**
	 * returns an iterator over the list of values bound to individual <code>individual</code> through object
	 * property <code>property</code> both parameters need to be instantiated
	 * 
	 * @param individual
	 * @param property
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTResourceIterator listValuesOfSubjObjPropertyPair(ARTResource individual,
			ARTURIResource property, boolean inferred, ARTResource... graphs) throws ModelAccessException;

	/**
	 * returns an iterator over the list of values allowed by this datarange
	 * 
	 * @param dataRange
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTLiteralIterator parseDataRange(ARTResource dataRange, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * given an iterator over RDF nodes, instantiates a set of triples realizing the datarange composed of
	 * elements in the iterator, assigned as range of property <code>property</code>
	 * 
	 * @param dataRange
	 * @param graphs
	 * @return
	 * @throws ModelAccessException
	 * @throws ModelUpdateException 
	 */
	public abstract String setDataRange(ARTURIResource property, RDFIterator<ARTLiteral> dataRangeIterator,
			ARTResource... graphs) throws ModelAccessException, ModelUpdateException;
	
	/**
	 * it adds a list of literal values (using an iterator over RDF ARTLiteral) to an existing datarange
	 * @param dataRange
	 * @param literals
	 * @param graphs
	 * @throws ModelUpdateException 
	 * @throws ModelAccessException 
	 */
	public abstract void addValuesToDatarange(ARTResource dataRange, Iterator <ARTLiteral> literals, 
			ARTResource... graphs) throws ModelAccessException, ModelUpdateException;
	
	/**
	 * it adds a literal value to an existing datarange
	 * @param dataRange
	 * @param lit
	 * @param graphs
	 * @throws ModelUpdateException 
	 * @throws ModelAccessException 
	 */
	public abstract void addValueToDatarange (ARTResource dataRange, ARTLiteral lit, 
			ARTResource... graphs) throws ModelAccessException, ModelUpdateException;

	/**
	 * check if the selected datarange has a particular literal as value
	 * @param dataRange
	 * @param lit
	 * @param graphs
	 * @return
	 * @throws ModelAccessException 
	 */
	public abstract boolean  hasValueInDatarange(ARTResource dataRange, ARTLiteral lit, 
			ARTResource... graphs) throws ModelAccessException;
	
	/**
	 * remove a ARTLiteral value from the desired datarange
	 * @param dataRange
	 * @param lit
	 * @param graphs
	 * @throws ModelAccessException 
	 * @throws ModelUpdateException 
	 */
	public abstract void removeValueFromDatarange(ARTResource dataRange, ARTLiteral lit,
			ARTResource... graphs) throws ModelAccessException, ModelUpdateException;
	
	/**
	 * removes an import statement from graphs <code>graphs</code>
	 * 
	 * @param URI
	 *            the baseURI of the ontology being imported
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void removeImportStatement(ARTURIResource URI, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * deletes an owl:Individual (optimized wrt {@link RDFModel#deleteResource(ARTResource, ARTResource...))}
	 * as an owl:Individual cannot appear as predicate of a triple)
	 * 
	 * @param res
	 * @param newURI
	 * @throws ModelUpdateException
	 */
	public abstract void deleteIndividual(ARTResource res, ARTResource... graphs) throws ModelUpdateException;

	/**
	 * renames an owl:Individual (optimized wrt {@link RDFModel#renameResource(ARTURIResource, String)} as an
	 * owl:Individual cannot appear as predicate of a triple)
	 * 
	 * @param res
	 * @param newURI
	 * @throws ModelUpdateException
	 */
	public abstract void renameIndividual(ARTURIResource res, String newURI, ARTResource... graphs)
			throws ModelUpdateException;
	
	
	// TODO: from here on, all the following methods have been added by Alfonso Turco for his Bachelor Thesis; check them
	
	/**
	     * Add an enumerated class with an identifier (a URI reference) to graphs <code>graphs</code>
	     * @param classURI
	     * @param resources
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addEnumeratedClass(String classURI, ArrayList<ARTNode> resources, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous enumerated class to graphs <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param resources
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addOneOf(String BnodeID, ArrayList<ARTNode> resources, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add a datarange to graphs <code>graphs</code>
	     * @param BnodeID
	     * @param resources
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addOneOfDataRange(String BnodeID, ArrayList<ARTLiteral> resources, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as a restriction on range (All Values) of a property to <code>graphs</code> 
	     * 
	     * @param BnodeID
	     * @param property
	     * @param resource
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addRestrictionOnPropertyAllValuesFrom(String BnodeID, ARTURIResource property, ARTResource resource, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as a restriction on range (Some Values) of a property to <code>graphs</code> 
	     * @param BnodeID
	     * @param property
	     * @param resource
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addRestrictionOnPropertySomeValuesFrom(String BnodeID, ARTURIResource property, ARTResource resource, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as a restriction on range (Has Value) of a property to <code>graphs</code> 
	     * 
	     * @param BnodeID
	     * @param property
	     * @param resourceOrLiteral
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addRestrictionOnPropertyHasValue(String BnodeID, ARTURIResource property, ARTNode resourceOrLiteral, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as a restriction on the minimum cardinality of property to <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param property
	     * @param literal
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addRestrictionOnCardinalityMinCardinality(String BnodeID, ARTURIResource property, String literal, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as a restriction on the maximum cardinality of property to <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param property
	     * @param literal
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addRestrictionOnCardinalityMaxCardinality(String BnodeID, ARTURIResource property, String literal, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as a restriction on the cardinality of property to <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param property
	     * @param literal
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addRestrictionOnCardinalityCardinality(String BnodeID, ARTURIResource property, String literal, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as intersection of a set of resources to <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param descriptions
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addIntersectionOf(String BnodeID, ArrayList<ARTResource> descriptions, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as the complement of the specified resource to <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param description
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addComplementOf(String BnodeID, ARTResource description, ARTResource... graphs)
	            throws ModelUpdateException;

	    /**
	     * Add an anonymous class as union of a set of resources to <code>graphs</code>
	     * 
	     * @param BnodeID
	     * @param descriptions
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addUnionOf(String BnodeID, ArrayList<ARTResource> descriptions, ARTResource... graphs)
	            throws ModelUpdateException;
	    
	    
	    
	    
	    /**
	     * Add a named equivalent class of the specified resource to <code>graphs</code>
	     * 
	     * @param StringURI
	     * @param equivalentClass
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addEquivalentClass(String classURI, ARTResource equivalentClass, ARTResource... graphs) 
	            throws ModelUpdateException;

	    
	    /**
	     * Add an named subclass of the specified resource to <code>graphs</code>
	     * 
	     * @param StringURI
	     * @param subClass
	     * @param graphs
	     * @throws ModelUpdateException 
	     */
	public void addSubClassOf(String classURI, ARTResource subClass, ARTResource... graphs) 
	            throws ModelUpdateException;
	    
	    
	    /**
		 * recursively explore (that is, runs along the transitive closure of) a property and fills the set
		 * <code>set</code> with all the objects which are blank node of his property
		 * 
		 * @param set
		 * @param resource
		 * @param prop
		 * @param graphs
		 * @throws ModelAccessException
		 */
	public void recursiveBNodeExploration(HashSet<ARTResource> set, ARTResource resource, ARTURIResource prop,
			ARTResource... graphs) throws ModelAccessException;

}